-- card: 6277 from stack: in -- bmap block id: 8749 -- flags: 0000 -- background id: 8327 -- name: XScrollBox ----- HyperTalk script ----- on opencard set the visible of field 1 to false -- background field set the scroll of card field 1 to 0 set the scroll of card field 2 to 0 end opencard on closecard set the visible of field 1 to true end closecard -- part 2 (field) -- low flags: 00 -- high flags: 4007 -- rect: left=384 top=62 right=290 bottom=491 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 3 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: scroller -- part 3 (button) -- low flags: 00 -- high flags: 8003 -- rect: left=76 top=298 right=320 bottom=176 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: XScrollBox ----- HyperTalk script ----- on mouseUp put empty into msg get XScrollBox(2,"Choose one of these:",card field "scroller","Help") if it is "Help" then put "You pushed the 'Help' button." else if it is empty then put "You pushed the 'Cancel' button." else put "Your choice was: " & it end if end mouseUp -- part 5 (field) -- low flags: 00 -- high flags: 2007 -- rect: left=18 top=32 right=290 bottom=384 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 20 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: XCMD Text -- part 6 (button) -- low flags: 00 -- high flags: 8003 -- rect: left=304 top=299 right=321 bottom=425 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Show LSC Source ----- HyperTalk script ----- on mouseUp get the visible of card field "source" set the visible of card field "source" to not it if it is false then set the name of me to "Hide LSC Source" else set the name of me to "Show LSC Source" end if end mouseUp -- part 7 (field) -- low flags: 81 -- high flags: 0007 -- rect: left=18 top=31 right=290 bottom=489 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 3 -- text size: 10 -- style flags: 0 -- line height: 13 -- part name: source -- part contents for card part 2 ----- text ----- able baker charlie dog ernest fox gamma horse ice cream jumping jack flash knockwurst liver monkey no way, jose occularity penelope qwerty rapscallion salubrious twinkle toes underwhelmed vermin wascally wabbit yokel zenzational -- part contents for card part 5 ----- text ----- XScrollBox version 1.4 Roger Brown XScrollBox is a HyperCard XFCN that creates a scrolling selection dialog box from any multi-lined container. Each line of the container is made into a selection line in the dialog. Only one line can be selected. The return value has two items: the number of the selection and the text of the selection. These are separated by commas as in normal HyperCard format. Selection can be made by : 1. double-clicking on a line. 2. single-clicking on a line, then pressing the OK button. 3. single-clicking on a line, then pressing the Return key. 4. typing the first letter(s) of a selection, then doing 1,2, or 3. (Note: type selection assumes that the lines are ordere alphabetically) 5. scrolling with up and down arrow keys, then doing 1,2 or 3. If the Cancel button is pressed, a null string is returned. It requires that the DITL and DLOG resources (1345) packaged with it are in the stack. The dialog is centered on the screen and sized to hold the width of the longest line and/or the prompt line, whichever is widest. It will not overrun the width of a Mac+ screen. INVOKING XScrollBox get XScrollBox(first,prompt,container,userButton) where first is a default selection in the list - either a number or a text string (0 if none). prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned further processing by the script. EXAMPLE ex. get XScrollBox(1,"Choose:",card field 1,"Help") if OK is pressed, returns : 1,text of line 1 of card field 1 REVISION HISTORY 1.1 center dialog box on any size screen 1.2 - add selection scrolling by typing and by cursor keys 1.3 - add text of chosen item to return value 1.4 -- 3/2/88 add optional user button -- part contents for card part 7 ----- text ----- /* XSCrollBox1.4.c */ /* © Trustees of Dartmouth College */ /* written in LightSpeed C © Think Technologies, Inc */ /* by Roger Brown 3/2/88 Courseware Development Group */ /* This is a HyperCard XFCN that creates a scrolling selection dialog box from any multi-lined container. Syntax is: get XScrollBox(first,prompt,container,userButton) ex. get XScrollBox(1,"Choose:",card field 1,"Help") returns: 1,text of line 1 of card field 1 where first is a default selection in the list - either a number or a text string (0 if none). prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned for further processing by the script. Each line of the container is made into a selection line in the dialog. Only one line can be selected. The return value has two items: the number of the selection and the text of the selection. These are separated by commas as in normal HyperCard format. Selection can be made by: 1. double-clicking on a line. 2. single-clicking on a line, then pressing the OK button. 3. single-clicking on a line, then pressing the Return key. 4. typing the first letter(s) of a selection, then doing 1,2, or 3. (Note: type selection assumes that the lines are ordered alphabetically) 5. scrolling with up and down arrow keys, then doing 1,2 or 3. If the Cancel button is pressed, a null string is returned. It requires that the DITL and DLOG resources packaged with it are in the stack. The dialog box is centered in the card window. To compile: create a project with this and MacTraps. Build as code resource type XFCN, ID 1345, name XScrollBox. */ #include "stddata_ctype.c" #include "QuickDraw.h" #include "EventMgr.h" #include "WindowMgr.h" #include "ResourceMgr.h" #include "ControlMgr.h" #include "DialogMgr.h" #include "strings.c" #include "ListMgr.h" #include "ToolboxUtil.h" #include "HyperXCmd.h" #include "XCmdGlue.inc.c" #define FALSE 0 #define TRUE !FALSE /* The following assembly routines manage register A4. They are required because we use global variables and access them from within functions that are passed as parameters to other functions. This is a LSC convention. */ #define RememberA4() _A4_(1) #define XCMDSetupA4() asm { move.l A4,-(sp) };_A4_(0) #define XCMDRestoreA4() asm { move.l (sp)+,A4 } /* globals */ #define kOKbutton 1 #define kCancel 2 #define kPrompt 3 #define kListItem 4 #define kOutliner 5 #define kUserButton 6 #define kTyping 99 int kScrollBarWidth = 15; int kStdLDEF = 0; int kDialogId = 1345; int kStringListId = 1345; int gCellWidth; int gCellHeight = 16; Rect dialogRect,listRect,cardRect; ListHandle theList; DialogPtr theListDialog; Str255 theResult,userButton; long theStartWith; Str255 startString; char startIsString; Handle resultHandle; CursHandle theCursor; char collector[32]; int charPos; long charTime; /* return max of 2 integers */ max(a,b) int a,b; { if (a>b) return a; return b; } /* return min of 2 integers */ min(a,b) { if (aleft = GetHCItem(str,1); itsRect->top = GetHCItem(str,2); itsRect->right = GetHCItem(str,3); itsRect->bottom = GetHCItem(str,4); } /* user item in dialog box to outline the default (ok) button */ pascal void OutlineButton (myWindow,itemNo) WindowPtr myWindow; int itemNo; { int iType; Handle iHandle; Rect iBox; XCMDSetupA4(); GetDItem(theListDialog, kOKbutton, &iType, &iHandle, &iBox); InsetRect(&iBox, -4, -4); PenSize(3, 3); FrameRoundRect(&iBox, 16, 16); PenNormal(); XCMDRestoreA4(); } /* User item in dialog box to display the selectin list */ pascal void DrawListItem (myWindow,itemNo) WindowPtr myWindow; int itemNo; /* draw the selection list */ { RgnHandle theRgn; Rect listFrame; XCMDSetupA4(); listFrame = (**theList).rView; InsetRect(&listFrame, -1, -1); FrameRect(&listFrame); theRgn = NewRgn(); RectRgn(theRgn, &(*theListDialog).portRect); LUpdate(theRgn, theList); DisposeRgn(theRgn); XCMDRestoreA4(); } /* string selection logic for selection via typed characters */ pascal int MySelect(aPtr,bPtr,aLen,bLen) Ptr aPtr,bPtr;int aLen,bLen; { if (IUMagString(aPtr,bPtr,aLen,bLen) ==1) return 0; return 1; } /* scroll selection list up or down */ VerticalScroll(c) char c; { Cell oldCell,aCell; XCMDSetupA4(); SetPt(&oldCell,0,0); if (!LGetSelect(TRUE,&oldCell,theList)) { /* get current selection */ SysBeep(0); /* no current selection */ return; } if (c==30) { SetPt(&aCell,0,max(0,oldCell.v-1)); } else if (c==31) { SetPt(&aCell,0,min((**theList).dataBounds.bottom-1,oldCell.v+1)); } if (EqualPt(oldCell,aCell)==1) { SysBeep(0); return; } LSetSelect(FALSE,oldCell,theList); /* clear current selection */ LSetSelect(TRUE,aCell,theList); /* set the new one */ LAutoScroll(theList); XCMDRestoreA4(); } /* Select by typing - a filter proc for ModalDialog. Simulates SGGetFile dialog action. */ pascal char NameSelect(theDialog,theEvent,itemHit) DialogPtr theDialog;EventRecord *theEvent;int *itemHit; { int c; long dummy; int iType; Handle iHandle; Rect iBox; char result; XCMDSetupA4(); result = FALSE; if ((theEvent->what == keyDown)||(theEvent->what == autoKey)) { if (TickCount() > charTime) charPos = 0; collector[charPos] = BitAnd(theEvent->message,charCodeMask); if ((collector[charPos] ==13)||(collector[charPos]==3)) { /* is CR, use as normal */ *itemHit = 1; GetDItem(theListDialog, kOKbutton, &iType, &iHandle, &iBox); HiliteControl(iHandle,inButton); result = TRUE; } else if ((collector[charPos]==31)||(collector[charPos]==30)) { /* cursor up/down */ VerticalScroll(collector[charPos]); charPos = 0; } else { charPos++; collector[charPos] = 0; *itemHit = 99; result = TRUE; charTime = TickCount()+45; } } XCMDRestoreA4(); return result; } /* Create, size, center, and fill in the selection box. Retuens 0 if any errors occur. */ int SetupScrollBox (prompt,theField) char *prompt; char *theField; { Rect dataBounds, itemBox,tempRect; char doVScroll, doHScroll; Point cellSize; Cell aCell,oldCell; int i,j, itemType,x,y; ControlHandle itemHandle; Str255 aString; long len; int fieldLen; int numLines,lineLen,maxLen,row; char done,c; int screenCenterX,screenCenterY; int dialogWidth; int dialogCenterX,dialogCenterY; int itemWidth,itemHeight; int itemHit; GrafPtr gp; Handle tempHandle; int numButtons; XCMDSetupA4(); if (strlen(userButton)>0) numButtons = 3; else numButtons = 2; /* size the dialog box */ dialogWidth = 200+8*strlen(userButton); /* minimum width to fit buttons at bottom */ /* make sure the prompt fits */ dialogWidth = max(dialogWidth,strlen(prompt)*8+20); /* find the longest line */ lineLen = maxLen = numLines = 0; fieldLen = strlen(theField); for (i=0;i 31) { aString[j] = theField[i]; j++; } if ((theField[i] ==13)||(i==(fieldLen-1))) { aString[j] = 0; SetPt(&aCell,0,row); row ++; lineLen = strlen(aString); LSetCell(&aString[0], lineLen, aCell, theList); j = 0; } } if (startIsString) { SetPt(&oldCell,0,0); LGetSelect(TRUE,&oldCell,theList); /* get current selection*/ SetPt(&aCell,0,0); if (LSearch(startString,strlen(startString),MySelect,&aCell,theList)) { if (!EqualPt(oldCell,aCell)) { LSetSelect(FALSE,oldCell,theList); /* clear current selection */ LSetSelect(TRUE,aCell,theList); /* set the new one */ LAutoScroll(theList); } } } else if ((theStartWith > 0)&&(theStartWith10) LAutoScroll(theList); } LDoDraw(TRUE, theList); /* now complete the two user items of the dialog */ itemBox = listRect; itemBox.right = itemBox.right + kScrollBarWidth; SetDItem(theListDialog, kListItem, userItem, DrawListItem, &itemBox); GetDItem(theListDialog,kOKbutton,&itemType,&itemHandle,&itemBox); SetDItem(theListDialog, kOutliner, userItem + itemDisable, OutlineButton, &itemBox); /* present the window up front */ ShowWindow(theListDialog); BringToFront(theListDialog); XCMDRestoreA4(); return 1; } DoListDialog () /* pose the dialog and handle it */ { int itemHit; Point aPoint; Cell oldCell,aCell; itemHit = charPos = 0; while (1) { ModalDialog(NameSelect, &itemHit); switch (itemHit) { case kOKbutton : return 1; break; case kCancel: return 0; break; case kListItem: SetPort(theListDialog); GetMouse(&aPoint); if (LClick(aPoint, 0, theList)) return 1; break; case kUserButton: return 2; break; case kTyping: SetPt(&oldCell,0,0); LGetSelect(TRUE,&oldCell,theList); /* get current selection*/ SetPt(&aCell,0,0); if (LSearch(collector,strlen(collector),MySelect,&aCell,theList)) { if (!EqualPt(oldCell,aCell)) { LSetSelect(FALSE,oldCell,theList); /* clear current selection */ LSetSelect(TRUE,aCell,theList); /* set the new one */ LAutoScroll(theList); } } break; } } } /* get the text of the selection made */ GetListSelection (aString) char *aString; { char someSelect; Cell aCell; int stringLength,t,b,i; Str255 num; long n; SetPt(&aCell, 0, 0); someSelect = LGetSelect(TRUE, &aCell, theList); if (someSelect==TRUE) { stringLength = 255; LGetCell(aString, &stringLength, aCell, theList); n = aCell.v+1; NumToString(n,num); PtoCstr(num); *(aString+stringLength) = 0; strcat(num,","); strcat(num,aString); strcpy(aString,num); } else { strcpy(aString,""); } } /* clean up memory */ PrepareToExit() { if (theList != NULL) LDispose(theList); if (theListDialog != NULL) DisposDialog(theListDialog); } /* create scroll box, present it, return user's selection */ pascal void XScrollBox(paramPtr) XCmdBlockPtr paramPtr; { Str255 result; Ptr start; Ptr thePrompt; Ptr theField; Ptr theUserButton; int status,i; Size len; theCursor = GetCursor(watchCursor); SetCursor(*theCursor); for (i=0;i<5;i++) { MoveHHi(paramPtr->params[i]); HLock(paramPtr->params[i]); } start = *(paramPtr->params[0]); startIsString = TRUE; for (i=0;iparams[1]); theField = *(paramPtr->params[2]); theUserButton = *(paramPtr->params[3]); if (GetHandleSize(paramPtr->params[3])>0) strcpy(userButton,theUserButton); else strcpy(userButton,""); GetCardRect(paramPtr,&cardRect); status = SetupScrollBox(thePrompt,theField); InitCursor(); if (status==1) { status = DoListDialog(); if (status==1) GetListSelection(theResult); else if (status==2) strcpy(theResult,userButton); else strcpy(theResult,""); } else strcpy(theResult,"Can't find dialog resource 1345 for XScrollBox XFCN"); len = 1+strlen(theResult); resultHandle = NewHandle(len); HLock(resultHandle); BlockMove(theResult,*resultHandle,len); HUnlock(resultHandle); paramPtr->returnValue = resultHandle; for (i=0;i<5;i++) HUnlock (paramPtr->params[i]); return; } /* this is the entry point for the XFCN */ pascal void main(paramPtr) XCmdBlockPtr paramPtr; { RememberA4(); XCMDSetupA4(); /* do this if you have global variables */ XScrollBox(paramPtr); /* run the main event loop */ PrepareToExit(); /* tidy up */ XCMDRestoreA4(); /* and this also */ return; }